import 'package:dartkit/dartkit.dart';
import 'package:test/test.dart';

abstract class Person {
  String get name;
  int get age;
}

class Parent implements Person, TreeNode<Person> {
  @override
  String name;
  @override
  int age;

  Parent(this.name, this.age);

  @override
  List<Person> children = [];
}

class Child implements Person {
  @override
  String name;
  @override
  int age;

  Child(this.name, this.age);
}

void main() {
  Parent root = Parent("root", 50);

  // root
  //   ├─a
  //   | ├─c
  //   | └─d
  //   └─b
  //     └─e
  setUp(() {
    final parentA = Parent("a", 30);
    parentA.children.add(Child("c", 10));
    parentA.children.add(Child("d", 10));
    final parentB = Parent("b", 30);
    parentB.children.add(Child("e", 10));
    root.children.add(parentA);
    root.children.add(parentB);
  });
  tearDown(() => root.children.clear());

  test("替换测试", () {
    // 将c替换为z
    final result = root.replace((x) => x.name == "c", Child("z", 30));
    // 预计能够成功
    expect(result, isTrue);
    // 能找到z，但找不到c了
    expect(root.find((x) => x.name == "z"), isNotNull);
    expect(root.find((x) => x.name == "c"), isNull);
  });

  test("寻找测试", () {
    // 寻找根部节点
    final rootFound = root.find((x) => x.name == "root");
    expect(rootFound, isNotNull);

    // 寻找子节点
    final e = root.find((x) => x.name == "e");
    expect(e, isNotNull);
    expect(e!.age, 10);

    // 寻找不存在的节点
    expect(() => root.fetch((x) => x.name == "abc"), isBug);
  });

  test("插入测试", () {
    // 在根部插入
    root.insert((x) => x.name == "root", Child("z", 30));
    expect(root.find((x) => x.name == "z"), isNotNull);
    // 在b节点插入
    root.insert((x) => x.name == "b", Child("x", 30));
    expect(root.find((x) => x.name == "x"), isNotNull);
    // 无法在Child节点插入
    expect(() => root.insert((x) => x.name == "e", Child("wrong", 10)),
        throwsException);
  });

  test("递归执行", () {
    // 除了root本身外，所有节点都会执行一次
    int count = 0;
    root.forEach((_) => count++);
    expect(count, 6);
  });

  test("map", () {
    // 统计所有人的名字
    List<String> names = root.map((x) => x.name);
    // 除了root以外，所有人的名字都在
    expect(names.length, 6);
    expect(names.contains("a"), isTrue);
    expect(names.contains("root"), isTrue);
  });

  test("sum统计", () {
    // 将每个人的年龄加起来
    int totalAge = root.sum<int>(0, (total, child) => total + child.age);
    // 包括root在内，共140岁
    expect(totalAge, 140);
  });

  test("删除", () {
    // 删除1个
    root.delete((x) => x.name == "e");
    expect(root.find((x) => x.name == "e"), isNull);

    // 删除多个
    root.deleteAll((x) => x.age == 10);
    expect(root.find((x) => x.age == 10), isNull);
  });
}
